//===--- Arrays.swift.gyb -------------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  Three generic, mutable array-like types with value semantics.
//
//  - `ContiguousArray<Element>` is a fast, contiguous array of `Element` with
//    a known backing store.
//
//  - `ArraySlice<Element>` presents an arbitrary subsequence of some
//    contiguous sequence of `Element`s.
//
//  - `Array<Element>` is like `ContiguousArray<Element>` when `Element` is not
//    a reference type or an Objective-C existential.  Otherwise, it may use
//    an `NSArray` bridged from Cocoa for storage.
//
//===----------------------------------------------------------------------===//

/// This type is used as a result of the _checkSubscript call to associate the
/// call with the array access call it guards.
public struct _DependenceToken {}

%{
  arrayTypes = [
    ('ContiguousArray', 'a `ContiguousArray` instance'),
    ('ArraySlice', 'an `ArraySlice` instance'),
    ('Array', 'an array'),
  ]
}%

% for (Self, a_Self) in arrayTypes:

%{
if True:
  contiguousCaveat = (
    ' If no such storage exists, it is first created.' if Self == 'Array'
    else '')

  if Self == 'ContiguousArray':
    SelfDocComment = """\
/// A contiguously stored array.
///
/// The `ContiguousArray` type is a specialized array that always stores its
/// elements in a contiguous region of memory. This contrasts with `Array`,
/// which can store its elements in either a contiguous region of memory or an
/// `NSArray` instance if its `Element` type is a class or `@objc` protocol.
///
/// If your array's `Element` type is a class or `@objc` protocol and you do
/// not need to bridge the array to `NSArray` or pass the array to Objective-C
/// APIs, using `ContiguousArray` may be more efficient and have more
/// predictable performance than `Array`. If the array's `Element` type is a
/// struct or enumeration, `Array` and `ContiguousArray` should have similar
/// efficiency.
///
/// For more information about using arrays, see `Array` and `ArraySlice`, with
/// which `ContiguousArray` shares most properties and methods."""
  elif Self == 'ArraySlice':
    SelfDocComment = """\
/// A slice of an `Array`, `ContiguousArray`, or `ArraySlice` instance.
///
/// The `ArraySlice` type makes it fast and efficient for you to perform
/// operations on sections of a larger array. Instead of copying over the
/// elements of a slice to new storage, an `ArraySlice` instance presents a
/// view onto the storage of a larger array. And because `ArraySlice`
/// presents the same interface as `Array`, you can generally perform the
/// same operations on a slice as you could on the original array.
///
/// For more information about using arrays, see `Array` and `ContiguousArray`,
/// with which `ArraySlice` shares most properties and methods.
///
/// Slices Are Views onto Arrays
/// ============================
///
/// For example, suppose you have an array holding the number of absences
/// from each class during a session.
///
///     let absences = [0, 2, 0, 4, 0, 3, 1, 0]
///
/// You want to compare the absences in the first half of the session with
/// those in the second half. To do so, start by creating two slices of the
/// `absences` array.
///
///     let midpoint = absences.count / 2
///
///     let firstHalf = absences.prefix(upTo: midpoint)
///     let secondHalf = absences.suffix(from: midpoint)
///
/// Neither the `firstHalf` nor `secondHalf` slices allocate any new storage
/// of their own. Instead, each presents a view onto the storage of the
/// `absences` array.
///
/// You can call any method on the slices that you might have called on the
/// `absences` array. To learn which half had more absences, use the
/// `reduce(_:combine:)` method to calculate each sum.
///
///     let firstHalfSum = firstHalf.reduce(0, combine: +)
///     let secondHalfSum = secondHalf.reduce(0, combine: +)
///
///     if firstHalfSum > secondHalfSum {
///         print("More absences in the first half.")
///     } else {
///         print("More absences in the second half.")
///     }
///     // Prints "More absences in the second half."
///
/// - Important: Long-term storage of `ArraySlice` instances is discouraged. A
///   slice holds a reference to the entire storage of a larger array, not
///   just to the portion it presents, even after the original array's lifetime
///   ends. Long-term storage of a slice may therefore prolong the lifetime of
///   elements that are no longer otherwise accessible, which can appear to be
///   memory and object leakage.
///
/// Slices Maintain Indices
/// =======================
///
/// Unlike `Array` and `ContiguousArray`, the starting index for an
/// `ArraySlice` instance isn't always zero. Slices maintain the same
/// indices of the larger array for the same elements, so the starting
/// index of a slice depends on how it was created, letting you perform
/// index-based operations on either a full array or a slice.
///
/// Sharing indices between collections and their subsequences is an important
/// part of the design of Swift's collection algorithms. Suppose you are
/// tasked with finding the first two days with absences in the session. To
/// find the indices of the two days in question, follow these steps:
///
/// 1) Call `index(where:)` to find the index of the first element in the
///    `absences` array that is greater than zero.
/// 2) Create a slice of the `absences` array starting after the index found in
///    step 1.
/// 3) Call `index(where:)` again, this time on the slice created in step 2.
///    Where in some languages you might pass a starting index into an
///    `indexOf` method to find the second day, in Swift you perform the same
///    operation on a slice of the original array.
/// 4) Print the results using the indices found in steps 1 and 3 on the
///    original `absences` array.
///
/// Here's an implementation of those steps:
///
///     if let i = absences.index(where: { $0 > 0 }) {                      // 1
///         let absencesAfterFirst = absences.suffix(from: i + 1)           // 2
///         if let j = absencesAfterFirst.index(where: { $0 > 0 }) {        // 3
///             print("The first day with absences had \(absences[i]).")    // 4
///             print("The second day with absences had \(absences[j]).")
///         }
///     }
///     // Prints "The first day with absences had 2."
///     // Prints "The second day with absences had 4."
///
/// In particular, note that `j`, the index of the second day with absences,
/// was found in a slice of the original array and then used to access a value
/// in the original `absences` array itself.
///
/// - Note: To safely reference the starting and ending indices of a slice,
///   always use the `startIndex` and `endIndex` properties instead of
///   specific values.
"""
  elif Self == 'Array':
    SelfDocComment = '''\
/// An ordered, random-access collection.
///
/// Arrays are one of the most commonly used data types in an app. You use
/// arrays to organize your app's data. Specifically, you use the `Array`
/// type to hold elements of a single type, the array's `Element` type. An
/// array's elements can be anything from an integer to a string to a
/// class.
///
/// Swift makes it easy to create arrays in your code using an array
/// literal: simply surround a comma-separated list of values with square
/// brackets. Without any other information, Swift creates an array that
/// includes the specified values, automatically inferring the array's
/// `Element` type. For example:
///
///     // An array of 'Int' elements
///     let oddNumbers = [1, 3, 5, 7, 9, 11, 13, 15]
///
///     // An array of 'String' elements
///     let streets = ["Albemarle", "Brandywine", "Chesapeake"]
///
/// You can create an empty array by specifying the `Element` type of your
/// array in the declaration. For example:
///
///     // Shortened forms are preferred
///     var emptyDoubles: [Double] = []
///
///     // The full type name is also allowed
///     var emptyFloats: Array<Float> = Array()
///
/// If you need an array that is preinitialized with a fixed number of
/// default values, use the `Array(repeating:count:)` initializer.
///
///     var digitCounts = Array(repeating: 0, count: 10)
///     print(digitCounts)
///     // Prints "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"
///
/// Accessing Array Values
/// ======================
///
/// When you need to perform an operation on all of an array's elements, use
/// a `for`-`in` loop to iterate through the array's contents.
///
///     for street in streets {
///         print("I don't live on \(street).")
///     }
///     // Prints "I don't live on Albemarle."
///     // Prints "I don't live on Brandywine."
///     // Prints "I don't live on Chesapeake."
///
/// Use the `isEmpty` property to check quickly whether an array has any
/// elements, or use the `count` property to find the number of elements in
/// the array.
///
///     if oddNumbers.isEmpty {
///         print("I don't know any odd numbers.")
///     } else {
///         print("I know \(oddNumbers.count) odd numbers.")
///     }
///     // Prints "I know 8 odd numbers."
///
/// Use the `first` and `last` properties for safe access to the value of the
/// array's first and last elements. If the array is empty, these properties
/// are `nil`.
///
///     if let firstElement = oddNumbers.first, lastElement = oddNumbers.last {
///         print(firstElement, lastElement, separator: ", ")
///     }
///     // Prints "1, 15"
///
///     print(emptyDoubles.first, emptyDoubles.last, separator: ", ")
///     // Prints "nil, nil"
///
/// You can access individual array elements through a subscript. The first
/// element of a nonempty array is always at index zero. You can
/// subscript an array with any integer from zero up to, but not including,
/// the count of the array. Using a negative number or an index equal to or
/// greater than `count` triggers a runtime error. For example:
///
///     print(oddNumbers[0], oddNumbers[3], separator: ", ")
///     // Prints "1, 7"
///
///     print(emptyDoubles[0])
///     // Triggers runtime error: Index out of range
///
/// See the `Sequence`, `Collection`, and `RangeReplaceableCollection`
/// protocols for more methods available to arrays.
///
/// Adding and Removing Elements
/// ============================
///
/// Suppose you need to store a list of the names of students that are
/// signed up for a class you're teaching. During the registration period,
/// you need to add and remove names as students add and drop the class.
///
///     var students = ["Ben", "Ivy", "Jordell"]
///
/// More students are signing up. Add single elements to the end of an array
/// by using the `append(_:)` method. Add multiple elements at once by passing
/// another array or a sequence of any kind to the `append(contentsOf:)`
/// method.
///
///     students.append("Maxime")
///     students.append(contentsOf: ["Shakia", "William"])
///
///     print(students)
///     // Prints "["Ben", "Ivy", "Jordell", "Maxime", "Shakia", "William"]"
///
/// Another last-minute addition! Add new elements into the middle of the
/// array by using the `insert(_:at:)` method for single elements and
/// by using `insert(contentsOf:at:)` to insert multiple elements from another
/// collection or array literal. The elements at that index and later are
/// shifted back to make room.
///
///     // Welcome, Liam!
///     students.insert("Liam", at: 3)
///
/// A couple of students can't take your class after all. Use the
/// `removeLast()` and `remove(at:)` methods to remove their names
/// from the array.
///
///     // Ben's family is moving to another state
///     students.remove(at: 0)
///
///     // William is signing up for a different class
///     students.removeLast()
///
///     print(students)
///     // Prints "["Ivy", "Jordell", "Liam", "Maxime", "Shakia"]"
///
/// On the first day, you learn that Maxime really prefers to go by Max.
/// Replace an existing element with a new value by assigning to the
/// subscript.
///
///     if let i = students.index(of: "Maxime") {
///         students[i] = "Max"
///     }
///
/// Growing the Size of an Array
/// ----------------------------
///
/// Every array reserves a specific amount of memory to hold its contents. When
/// you add elements to an array and that array begins to exceed its reserved
/// capacity, the array allocates a larger region of memory and copies its
/// elements into the new storage. The new storage is a multiple of the
/// old storage's size. This exponential growth strategy means that appending
/// an element happens in constant time, averaging the performance of many
/// append operations. Append operations that trigger reallocation have a
/// performance cost, but they occur less and less often as the array grows
/// larger.
///
/// If you know approximately how many elements you will need to store, use
/// the `reserveCapacity(_:)` method before appending to the array to avoid
/// intermediate reallocations. Use the `capacity` and `count` properties
/// to determine how many more elements the array can store without
/// allocating larger storage.
///
/// For arrays of most `Element` types, this storage is a contiguous block
/// of memory. For arrays with an `Element` type that is a class or `@objc`
/// protocol type, this storage can be a contiguous block of memory or an
/// instance of `NSArray`. Because any arbitrary subclass of `NSArray` can
/// become an `Array`, there are no guarantees about representation or
/// efficiency in this case.
///
/// Modifying Copies of Arrays
/// ==========================
///
/// Each array has an independent value that includes the values of all of
/// its elements. For simple types such as integers and other structures,
/// this means that when you change a value in one array, the value of that
/// element does not change in any copies of the array. For example:
///
///     var numbers = [1, 2, 3, 4, 5]
///     var numbersCopy = numbers
///     numbers[0] = 100
///     print(numbers)
///     // Prints "[100, 2, 3, 4, 5]"
///     print(numbersCopy)
///     // Prints "[1, 2, 3, 4, 5]"
///
/// If the elements in an array are instances of a class, the semantics are
/// the same, though they might appear different at first. In this case,
/// the values stored in the array are references to objects that live
/// outside the array. If you change a reference to an object in one array,
/// only that array has a reference to the new object. However, if two
/// arrays contain references to the same object, you can observe changes
/// to that object's properties from both arrays. For example:
///
///     // An integer type with reference semantics
///     class IntegerReference {
///         var value = 10
///     }
///     var firstIntegers = [IntegerReference(), IntegerReference()]
///     var secondIntegers = firstIntegers
///
///     // Modifications to an instance are visible from either array
///     firstIntegers[0].value = 100
///     print(secondIntegers[0].value)
///     // Prints "100"
///
///     // Replacements, additions, and removals are still visible
///     // only in the modified array
///     firstIntegers[0] = IntegerReference()
///     print(firstIntegers[0].value)
///     // Prints "10"
///     print(secondIntegers[0].value)
///     // Prints "100"
///
/// Arrays, like all variable-size collections in the standard library, use
/// copy-on-write optimization. Multiple copies of an array share the same
/// storage until you modify one of the copies. When that happens, the
/// array being modified replaces its storage with a uniquely owned copy of
/// itself, which is then modified in place. Optimizations are sometimes
/// applied that can reduce the amount of copying.
///
/// This means that if an array is sharing storage with other copies, the
/// first mutating operation on that array incurs the cost of copying the
/// array. An array that is the sole owner of its storage can perform
/// mutating operations in place.
///
/// In the example below, a `numbers` array is created along with two copies
/// that share the same storage. When the original `numbers` array is
/// modified, it makes a unique copy of its storage before making the
/// modification. Further modifications to `numbers` are made in place,
/// while the two copies continue to share the original storage.
///
///     var numbers = [1, 2, 3, 4, 5]
///     var firstCopy = numbers
///     var secondCopy = numbers
///
///     // The storage for 'numbers' is copied here
///     numbers[0] = 100
///     numbers[1] = 200
///     numbers[2] = 300
///     // 'numbers' is [100, 200, 300, 4, 5]
///     // 'firstCopy' and 'secondCopy' are [1, 2, 3, 4, 5]
///
/// Bridging Between Array and NSArray
/// ==================================
///
/// When you need to access APIs that expect data in an `NSArray` instance
/// instead of `Array`, use the type-cast operator (`as`) to bridge your
/// instance. For bridging to be possible, the `Element` type of your array
/// must be a class, an `@objc` protocol (a protocol imported from Objective-C
/// or marked with the `@objc` attribute), or a type that bridges to a
/// Foundation type.
///
/// The following example shows how you can bridge an `Array` instance to
/// `NSArray` to use the `write(to:atomically:)` method. In this
/// example, the `colors` array can be bridged to `NSArray` because its
/// `String` elements bridge to `NSString`. The compiler prevents bridging
/// the `moreColors` array, on the other hand, because its `Element` type
/// is `Optional<String>`, which does *not* bridge to a Foundation type.
///
///     let colors = ["periwinkle", "rose", "moss"]
///     let moreColors: [String?] = ["ochre", "pine"]
///
///     let url = NSURL(fileURLWithPath: "names.plist")
///     (colors as NSArray).write(to: url, atomically: true)
///     // true
///
///     (moreColors as NSArray).write(to: url, atomically: true)
///     // error: cannot convert value of type '[String?]' to type 'NSArray'
///
/// Bridging from `Array` to `NSArray` takes O(1) time and O(1) space if the
/// array's elements are already instances of a class or an `@objc`
/// protocol; otherwise, it takes O(n) time and space.
///
/// Bridging from `NSArray` to `Array` first calls the `copy(with:)`
/// (`- copyWithZone:` in Objective-C) method on the array to get an immutable
/// copy and then performs additional Swift bookkeeping work that takes O(1)
/// time. For instances of `NSArray` that are already immutable,
/// `copy(with:)` usually returns the same array in O(1) time; otherwise,
/// the copying performance is unspecified. The instances of `NSArray` and
/// `Array` share storage using the same copy-on-write optimization that is
/// used when two instances of `Array` share storage.
///
/// - Note: The `ContiguousArray` and `ArraySlice` types are not bridged;
///   instances of those types always have a contiguous block of memory as
///   their storage.
/// - SeeAlso: `ContiguousArray`, `ArraySlice`, `Sequence`, `Collection`,
///   `RangeReplaceableCollection`'''
  # FIXME: Write about Array up/down-casting.
  else:
    raise ValueError('Unhandled case: ' + Self)
}%

${SelfDocComment}
% if Self != 'ArraySlice':
@_fixed_layout
%end
public struct ${Self}<Element>
  : RandomAccessCollection,
    MutableCollection,
    _DestructorSafeContainer
{

  public typealias Index = Int
  public typealias Iterator = IndexingIterator<${Self}>

%if Self == 'ArraySlice':
  /// The position of the first element in a nonempty array.
  ///
  /// If the array is empty, `startIndex` is equal to `endIndex`.
%else:
  /// The position of the first element in a nonempty array.
  ///
  /// For an instance of `${Self}`, `startIndex` is always zero. If the array
  /// is empty, `startIndex` is equal to `endIndex`.
%end
  public var startIndex: Int {
%if Self == 'ArraySlice':
    return _buffer.startIndex
%else:
    return 0
%end
  }

  /// The array's "past the end" position---that is, the position one greater
  /// than the last valid subscript argument.
  ///
  /// When you need a range that includes the last element of an array, use the
  /// half-open range operator (`..<`) with `endIndex`. The `..<` operator
  /// creates a range that doesn't include the upper bound, so it's always
  /// safe to use with `endIndex`. For example:
  ///
  ///     let numbers = [10, 20, 30, 40, 50]
  ///     if let i = numbers.index(of: 30) {
  ///         print(numbers[i ..< numbers.endIndex])
  ///     }
  ///     // Prints "[30, 40, 50]"
  ///
  /// If the array is empty, `endIndex` is equal to `startIndex`.
  public var endIndex: Int {
%if Self == 'ArraySlice':
    return _buffer.endIndex
%else:
    return _getCount()
%end
  }

  public func index(after i: Int) -> Int {
    // NOTE: this is a manual specialization of index movement for a Strideable
    // index that is required for Array performance.  The optimizer is not
    // capable of creating partial specializations yet.
    // NOTE: Range checks are not performed here, because it is done later by
    // the subscript function.
    return i + 1
  }

  public func formIndex(after i: inout Int) {
    // NOTE: this is a manual specialization of index movement for a Strideable
    // index that is required for Array performance.  The optimizer is not
    // capable of creating partial specializations yet.
    // NOTE: Range checks are not performed here, because it is done later by
    // the subscript function.
    i += 1
  }

  public func index(before i: Int) -> Int {
    // NOTE: this is a manual specialization of index movement for a Strideable
    // index that is required for Array performance.  The optimizer is not
    // capable of creating partial specializations yet.
    // NOTE: Range checks are not performed here, because it is done later by
    // the subscript function.
    return i - 1
  }

  public func formIndex(before i: inout Int) {
    // NOTE: this is a manual specialization of index movement for a Strideable
    // index that is required for Array performance.  The optimizer is not
    // capable of creating partial specializations yet.
    // NOTE: Range checks are not performed here, because it is done later by
    // the subscript function.
    i -= 1
  }

  /// Returns an index that is the specified distance from the given index.
  ///
  /// The following example obtains an index advanced four positions from an
  /// array's starting index and then prints the element at that position.
  ///
  ///     let numbers = [10, 20, 30, 40, 50]
  ///     let i = numbers.index(numbers.startIndex, offsetBy: 4)
  ///     print(numbers[i])
  ///     // Prints "50"
  ///
  /// Advancing an index beyond a collection's ending index or offsetting it
  /// before a collection's starting index may trigger a runtime error. The
  /// value passed as `n` must not result in such an operation.
  ///
  /// - Parameters:
  ///   - i: A valid index of the array.
  ///   - n: The distance to offset `i`.
  /// - Returns: An index offset by `n` from the index `i`. If `n` is positive,
  ///   this is the same value as the result of `n` calls to `index(after:)`.
  ///   If `n` is negative, this is the same value as the result of `-n` calls
  ///   to `index(before:)`.
  ///
  /// - Precondition:
  ///   - If `n > 0`, `n <= self.distance(from: i, to: self.endIndex)`
  ///   - If `n < 0`, `n >= self.distance(from: i, to: self.startIndex)`
  /// - Complexity: O(1)
  public func index(_ i: Int, offsetBy n: Int) -> Int {
    // NOTE: this is a manual specialization of index movement for a Strideable
    // index that is required for Array performance.  The optimizer is not
    // capable of creating partial specializations yet.
    // NOTE: Range checks are not performed here, because it is done later by
    // the subscript function.
    return i + n
  }

  /// Returns an index that is the specified distance from the given index,
  /// unless that distance is beyond a given limiting index.
  ///
  /// The following example obtains an index advanced four positions from an
  /// array's starting index and then prints the element at that position. The
  /// operation doesn't require going beyond the limiting `numbers.endIndex`
  /// value, so it succeeds.
  ///
  ///     let numbers = [10, 20, 30, 40, 50]
  ///     let i = numbers.index(numbers.startIndex,
  ///                           offsetBy: 4,
  ///                           limitedBy: numbers.endIndex)
  ///     print(numbers[i])
  ///     // Prints "50"
  ///
  /// The next example attempts to retrieve an index ten positions from
  /// `numbers.startIndex`, but fails, because that distance is beyond the
  /// index passed as `limit`.
  ///
  ///     let j = numbers.index(numbers.startIndex,
  ///                           offsetBy: 10,
  ///                           limitedBy: numbers.endIndex)
  ///     print(j)
  ///     // Prints "nil"
  ///
  /// Advancing an index beyond a collection's ending index or offsetting it
  /// before a collection's starting index may trigger a runtime error. The
  /// value passed as `n` must not result in such an operation.
  ///
  /// - Parameters:
  ///   - i: A valid index of the array.
  ///   - n: The distance to offset `i`.
  ///   - limit: A valid index of the collection to use as a limit. If `n > 0`,
  ///     `limit` has no effect if it is less than `i`. Likewise, if `n < 0`,
  ///     `limit` has no effect if it is greater than `i`.
  /// - Returns: An index offset by `n` from the index `i`, unless that index
  ///   would be beyond `limit` in the direction of movement. In that case,
  ///   the method returns `nil`.
  ///
  /// - SeeAlso: `index(_:offsetBy:)`, `formIndex(_:offsetBy:limitedBy:)`
  /// - Complexity: O(1)
  public func index(
    _ i: Int, offsetBy n: Int, limitedBy limit: Int
  ) -> Int? {
    // NOTE: this is a manual specialization of index movement for a Strideable
    // index that is required for Array performance.  The optimizer is not
    // capable of creating partial specializations yet.
    // NOTE: Range checks are not performed here, because it is done later by
    // the subscript function.
    let l = limit - i
    if n > 0 ? l >= 0 && l < n : l <= 0 && n < l {
      return nil
    }
    return i + n
  }

  /// Returns the distance between two indices.
  ///
  /// - Parameters:
  ///   - start: A valid index of the collection.
  ///   - end: Another valid index of the collection. If `end` is equal to
  ///     `start`, the result is zero.
  /// - Returns: The distance between `start` and `end`.
  public func distance(from start: Int, to end: Int) -> Int {
    // NOTE: this is a manual specialization of index movement for a Strideable
    // index that is required for Array performance.  The optimizer is not
    // capable of creating partial specializations yet.
    // NOTE: Range checks are not performed here, because it is done later by
    // the subscript function.
    return end - start
  }

  public func _failEarlyRangeCheck(_ index: Int, bounds: Range<Int>) {
    // NOTE: This method is a no-op for performance reasons.
  }

  public func _failEarlyRangeCheck(_ range: Range<Int>, bounds: Range<Int>) {
    // NOTE: This method is a no-op for performance reasons.
  }

  public typealias Indices = CountableRange<Int>

  /// Accesses the element at the specified position.
  ///
  /// For example:
  ///
  ///     var streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
  ///     streets[1] = "Butler"
  ///     print(streets[1])
  ///     // Prints "Butler"
  ///
  /// - Parameter index: The position of the element to access. `index` must be
  ///   greater than or equal to `startIndex` and less than `endIndex`.
  ///
  /// - Complexity: Reading an element from an array is O(1). Writing is O(1)
  ///   unless the array's storage is shared with another array, in which case
  ///   writing is O(*n*), where *n* is the length of the array.
%if Self == 'Array':
  ///   If the array uses a bridged `NSArray` instance as its storage, the
  ///   efficiency is unspecified.
%end
  public subscript(index: Int) -> Element {
    get {
      // This call may be hoisted or eliminated by the optimizer.  If
      // there is an inout violation, this value may be stale so needs to be 
      // checked again below.
      let wasNativeTypeChecked = _hoistableIsNativeTypeChecked()
      
      // Make sure the index is in range and wasNativeTypeChecked is
      // still valid.
      let token = _checkSubscript(
        index, wasNativeTypeChecked: wasNativeTypeChecked)

      return _getElement(
        index, wasNativeTypeChecked: wasNativeTypeChecked,
        matchingSubscriptCheck: token)
    }
    mutableAddressWithPinnedNativeOwner {
      _makeMutableAndUniqueOrPinned() // makes the array native, too
      _checkSubscript_native(index)   
      return (_getElementAddress(index), Builtin.tryPin(_getOwner_native()))
    }
  }

  /// Accesses a contiguous subrange of the array's elements.
  ///
  /// The returned `ArraySlice` instance uses the same indices for the same
  /// elements as the original array. In particular, that slice, unlike an
  /// array, may have a nonzero `startIndex` and an `endIndex` that is not
  /// equal to `count`. Always use the slice's `startIndex` and `endIndex`
  /// properties instead of assuming that its indices start or end at a
  /// particular value.
  ///
  /// This example demonstrates getting a slice of an array of strings, finding
  /// the index of one of the strings in the slice, and then using that index
  /// in the original array.
  ///
  ///     let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
  ///     let streetsSlice = streets[2 ..< streets.endIndex]
  ///     print(streetsSlice)
  ///     // Prints "["Channing", "Douglas", "Evarts"]"
  ///
  ///     let i = streetsSlice.index(of: "Evarts")    // 4
  ///     print(streets[i!])
  ///     // Prints "Evarts"
  ///
  /// - Parameter bounds: A range of integers. The bounds of the range must be
  ///   valid indices of the array.
%if Self != 'ArraySlice':
  ///
  /// - SeeAlso: `ArraySlice`
%end
  public subscript(bounds: Range<Int>) -> ArraySlice<Element> {
    get {
      _checkIndex(bounds.lowerBound)
      _checkIndex(bounds.upperBound)
      return ArraySlice(_buffer: _buffer[bounds])
    }
    set(rhs) {
      _checkIndex(bounds.lowerBound)
      _checkIndex(bounds.upperBound)
      if self[bounds]._buffer.identity != rhs._buffer.identity {
        self.replaceSubrange(bounds, with: rhs)
      }
    }
  }

  //===--- private --------------------------------------------------------===//

  /// Returns `true` if the array is native and does not need a deferred
  /// type check.  May be hoisted by the optimizer, which means its
  /// results may be stale by the time they are used if there is an
  /// inout violation in user code.
  @_semantics("array.props.isNativeTypeChecked")
  public // @testable
  func _hoistableIsNativeTypeChecked() -> Bool {
   return _buffer.arrayPropertyIsNativeTypeChecked
  }

  @_semantics("array.get_count")
  internal func _getCount() -> Int {
    return _buffer.count
  }
  @_semantics("array.get_capacity")
  internal func _getCapacity() -> Int {
    return _buffer.capacity
  }

  /// - Precondition: The array has a native buffer.
  @_semantics("array.owner")
  internal func _getOwnerWithSemanticLabel_native() -> Builtin.NativeObject {
    return Builtin.castToNativeObject(_buffer.nativeOwner)
  }

  /// - Precondition: The array has a native buffer.
  @inline(__always)
  internal func _getOwner_native() -> Builtin.NativeObject {
#if _runtime(_ObjC)
    if _isClassOrObjCExistential(Element.self) {
      // We are hiding the access to '_buffer.owner' behind
      // _getOwner() to help the compiler hoist uniqueness checks in
      // the case of class or Objective-C existential typed array
      // elements. 
      return _getOwnerWithSemanticLabel_native()
    }
#endif
    // In the value typed case the extra call to
    // _getOwnerWithSemanticLabel_native hinders optimization.
    return Builtin.castToNativeObject(_buffer.owner)
  }

  // FIXME(ABI): move to an initializer on _Buffer.
  static internal func _copyBuffer(_ buffer: inout _Buffer) {
    let newBuffer = _ContiguousArrayBuffer<Element>(
      uninitializedCount: buffer.count, minimumCapacity: buffer.count)
    buffer._copyContents(
      subRange: Range(buffer.indices),
      initializing: newBuffer.firstElementAddress)
    buffer = _Buffer(newBuffer, shiftedToStartIndex: buffer.startIndex)
  }

  @_semantics("array.make_mutable")
  internal mutating func _makeMutableAndUnique() {
    if _slowPath(!_buffer.isMutableAndUniquelyReferenced()) {
      ${Self}._copyBuffer(&_buffer)
    }
  }

  @_semantics("array.make_mutable")
  internal mutating func _makeMutableAndUniqueOrPinned() {
    if _slowPath(!_buffer.isMutableAndUniquelyReferencedOrPinned()) {
      ${Self}._copyBuffer(&_buffer)
    }
  }


  /// Check that the given `index` is valid for subscripting, i.e.
  /// `0 ≤ index < count`.
  @inline(__always)
  internal func _checkSubscript_native(_ index: Int) {
% if Self != 'Array':
    _buffer._checkValidSubscript(index)
% else:
    _ = _checkSubscript(index, wasNativeTypeChecked: true)
% end
  }

  /// Check that the given `index` is valid for subscripting, i.e.
  /// `0 ≤ index < count`.
  @_semantics("array.check_subscript")
  public // @testable
  func _checkSubscript(
    _ index: Int, wasNativeTypeChecked: Bool
  ) -> _DependenceToken {
#if _runtime(_ObjC)
% if Self == 'Array':
    _buffer._checkInoutAndNativeTypeCheckedBounds(
      index, wasNativeTypeChecked: wasNativeTypeChecked)
% else:
    _buffer._checkValidSubscript(index)
% end
#else
    _buffer._checkValidSubscript(index)
#endif
    return _DependenceToken()
  }

  /// Check that the specified `index` is valid, i.e. `0 ≤ index ≤ count`.
  @_semantics("array.check_index")
  internal func _checkIndex(_ index: Int) {
    _precondition(index <= endIndex, "${Self} index out of range")
    _precondition(index >= startIndex, "Negative ${Self} index is out of range")
  }

  @_semantics("array.get_element")
  @inline(__always)
  public // @testable
  func _getElement(
    _ index: Int,
    wasNativeTypeChecked : Bool,
    matchingSubscriptCheck: _DependenceToken
  ) -> Element {
#if ${'_runtime(_ObjC)' if Self == 'Array' else 'false'}
    return _buffer.getElement(index, wasNativeTypeChecked: wasNativeTypeChecked)
#else
    return _buffer.getElement(index)
#endif
  }

  @_semantics("array.get_element_address")
  internal func _getElementAddress(_ index: Int) -> UnsafeMutablePointer<Element> {
    return _buffer.subscriptBaseAddress + index
  }

%if Self == 'Array':
#if _runtime(_ObjC)
  public typealias _Buffer = _ArrayBuffer<Element>
#else
  public typealias _Buffer = _ContiguousArrayBuffer<Element>
#endif
%elif Self == 'ArraySlice':
  public typealias _Buffer = _SliceBuffer<Element>
%else:
  public typealias _Buffer = _${Self.strip('_')}Buffer<Element>
%end

  /// Initialization from an existing buffer does not have "array.init"
  /// semantics because the caller may retain an alias to buffer.
  public // @testable
  init(_buffer: _Buffer) {
    self._buffer = _buffer
  }

%if Self == 'ArraySlice':
  /// Initialization from an existing buffer does not have "array.init"
  /// semantics because the caller may retain an alias to buffer.
  public // @testable
  init(_buffer: _ContiguousArrayBuffer<Element>) {
    self.init(_buffer: _Buffer(_buffer, shiftedToStartIndex: 0))
  }
%end

  public var _buffer: _Buffer
}

extension ${Self} : ArrayLiteralConvertible {
%if Self == 'Array':
  // Optimized implementation for Array
  /// Creates an array from the given array literal.
  ///
  /// Do not call this initializer directly. It is used by the compiler
  /// when you use an array literal. Instead, create a new array by using an
  /// array literal as its value. To do this, enclose a comma-separated list of
  /// values in square brackets.
  ///
  /// Here, an array of strings is created from an array literal holding
  /// only strings.
  ///
  ///     let ingredients = ["cocoa beans", "sugar", "cocoa butter", "salt"]
  ///
  /// - Parameter elements: A variadic list of elements of the new array.
  public init(arrayLiteral elements: Element...) {
    self = elements
  }
%else:
  /// Creates an array from the given array literal.
  ///
  /// Do not call this initializer directly. It is used by the compiler when
  /// you use an array literal. Instead, create a new array by using an array
  /// literal as its value. To do this, enclose a comma-separated list of
  /// values in square brackets.
  ///
  /// Here, an array of strings is created from an array literal holding only
  /// strings:
  ///
  ///     let ingredients: ${Self} =
  ///           ["cocoa beans", "sugar", "cocoa butter", "salt"]
  ///
  /// - Parameter elements: A variadic list of elements of the new array.
  public init(arrayLiteral elements: Element...) {
    self.init(_buffer: _extractOrCopyToNativeArrayBuffer(elements._buffer))
  }
%end
}

%if Self == 'Array':

/// Returns an Array of `_count` uninitialized elements using the
/// given `storage`, and a pointer to uninitialized memory for the
/// first element.
///
/// This function is referenced by the compiler to allocate array literals.
///
/// - Precondition: `storage` is `_ContiguousArrayStorage`.
@inline(__always)
public // COMPILER_INTRINSIC
func _allocateUninitializedArray<Element>(_  builtinCount: Builtin.Word)
    -> (Array<Element>, Builtin.RawPointer) {
  let count = Int(builtinCount)
  if count > 0 {
    // Doing the actual buffer allocation outside of the array.uninitialized
    // semantics function enables stack propagation of the buffer.
    let bufferObject = ManagedBufferPointer<_ArrayBody, Element>(
      _uncheckedBufferClass: _ContiguousArrayStorage<Element>.self,
      minimumCapacity: count)

    let (array, ptr) = Array<Element>._adoptStorage(
      bufferObject.buffer, count: count)
    return (array, ptr._rawValue)
  }
  // For an empty array no buffer allocation is needed.
  let (array, ptr) = Array<Element>._allocateUninitialized(count)
  return (array, ptr._rawValue)
}

// Referenced by the compiler to deallocate array literals on the
// error path.
@_semantics("array.dealloc_uninitialized")
public func _deallocateUninitialized${Self}<Element>(
  _ array: ${Self}<Element>
) {
  var array = array
  array._deallocateUninitialized()
}
%end

extension ${Self} : RangeReplaceableCollection, _ArrayProtocol {
  /// Creates a new, empty array.
  ///
  /// This is equivalent to initializing with an empty array literal.
  /// For example:
  ///
  ///     var emptyArray = Array<Int>()
  ///     print(emptyArray.isEmpty)
  ///     // Prints "true"
  ///
  ///     emptyArray = []
  ///     print(emptyArray.isEmpty)
  ///     // Prints "true"
  @_semantics("array.init")
  public init() {
    _buffer = _Buffer()
  }

  /// Creates an array containing the elements of a sequence.
  ///
  /// You can use this initializer to create an array from any other type that
  /// conforms to the `Sequence` protocol. For example, you might want to
  /// create an array with the integers from 1 through 7. Use this initializer
  /// around a range instead of typing all those numbers in an array literal.
  ///
  ///     let numbers = Array(1...7)
  ///     print(numbers)
  ///     // Prints "[1, 2, 3, 4, 5, 6, 7]"
  ///
  /// You can also use this initializer to convert a complex sequence or
  /// collection type back to an array. For example, the `keys` property of
  /// a dictionary isn't an array with its own storage, it's a collection
  /// that maps its elements from the dictionary only when they're
  /// accessed, saving the time and space needed to allocate an array. If
  /// you need to pass those keys to a method that takes an array, however,
  /// use this initializer to convert that list from its type of
  /// `LazyMapCollection<Dictionary<String, Int>, Int>` to a simple
  /// `[String]`.
  ///
  ///     func cacheImagesWithNames(names: [String]) {
  ///         // custom image loading and caching
  ///      }
  /// 
  ///     let namedHues: [String: Int] = ["Vermillion": 18, "Magenta": 302,
  ///             "Gold": 50, "Cerise": 320]
  ///     let colorNames = Array(namedHues.keys)
  ///     cacheImagesWithNames(colorNames)
  /// 
  ///     print(colorNames)
  ///     // Prints "["Gold", "Cerise", "Magenta", "Vermillion"]"
  ///
  /// - Parameter s: The sequence of elements to turn into an array.
  public init<S : Sequence>(_ s: S)
    where S.Iterator.Element == Element {

    self = ${Self}(_buffer: _Buffer(s._copyToNativeArrayBuffer(),
      shiftedToStartIndex: 0))
  }

  /// Creates a new array containing the specified number of a single, repeated
  /// value.
  ///
  /// Here's an example of creating an array initialized with five strings
  /// containing the letter *Z*.
  ///
  ///     let fiveZs = Array(repeating: "Z", count: 5)
  ///     print(fiveZs)
  ///     // Prints "["Z", "Z", "Z", "Z", "Z"]"
  ///
  /// - Parameters:
  ///   - repeatedValue: The element to repeat.
  ///   - count: The number of times to repeat the value passed in the
  ///     `repeating` parameter. `count` must be zero or greater.
  @_semantics("array.init")
  public init(repeating repeatedValue: Element, count: Int) {
    var p: UnsafeMutablePointer<Element>
    (self, p) = ${Self}._allocateUninitialized(count)
    for _ in 0..<count {
      p.initialize(with: repeatedValue)
      p += 1
    }
  }

  @inline(never)
  internal static func _allocateBufferUninitialized(
    minimumCapacity: Int
  ) -> _Buffer {
    let newBuffer = _ContiguousArrayBuffer<Element>(
      uninitializedCount: 0, minimumCapacity: minimumCapacity)
    return _Buffer(newBuffer, shiftedToStartIndex: 0)
  }

  /// Construct a ${Self} of `count` uninitialized elements.
  internal init(_uninitializedCount count: Int) {
    _precondition(count >= 0, "Can't construct ${Self} with count < 0")
    // Note: Sinking this constructor into an else branch below causes an extra
    // Retain/Release.
    _buffer = _Buffer()
    if count > 0 {
      // Creating a buffer instead of calling reserveCapacity saves doing an
      // unnecessary uniqueness check. We disable inlining here to curb code
      // growth.
      _buffer = ${Self}._allocateBufferUninitialized(minimumCapacity: count)
      _buffer.count = count
    }
    // Can't store count here because the buffer might be pointing to the
    // shared empty array.
  }

  /// Entry point for `Array` literal construction; builds and returns
  /// a ${Self} of `count` uninitialized elements.
  @_versioned
  @_semantics("array.uninitialized")
  internal static func _allocateUninitialized(
    _ count: Int
  ) -> (${Self}, UnsafeMutablePointer<Element>) {
    let result = ${Self}(_uninitializedCount: count)
    return (result, result._buffer.firstElementAddress)
  }

%if Self == 'Array':

  /// Returns an Array of `count` uninitialized elements using the
  /// given `storage`, and a pointer to uninitialized memory for the
  /// first element.
  ///
  /// - Precondition: `storage is _ContiguousArrayStorage`.
  @_versioned
  @_semantics("array.uninitialized")
  internal static func _adoptStorage(
    _ storage: AnyObject, count: Int
  ) -> (Array, UnsafeMutablePointer<Element>) {
    
    _sanityCheck(
      storage is _ContiguousArrayStorage<Element>, "Invalid array storage type")
    
    let innerBuffer = _ContiguousArrayBuffer<Element>(
      count: count,
      storage: unsafeDowncast(
        storage, to: _ContiguousArrayStorage<Element>.self))
    
    return (
      Array(_buffer: _Buffer(innerBuffer, shiftedToStartIndex: 0)),
        innerBuffer.firstElementAddress)
  }

  /// Entry point for aborting literal construction: deallocates
  /// a ${Self} containing only uninitialized elements.
  internal mutating func _deallocateUninitialized() {
    // Set the count to zero and just release as normal.
    // Somewhat of a hack.
    _buffer.count = 0
  }
%end

  /// The number of elements in the array.
  public var count: Int {
    return _getCount()
  }

  /// The total number of elements that the array can contain using its current
  /// storage.
  ///
  /// If the array grows larger than its capacity, it discards its current
  /// storage and allocates a larger one.
  ///
  /// The following example creates an array of integers from an array literal,
  /// then appends the elements of another collection. Before appending, the
  /// array allocates new storage that is large enough store the resulting
  /// elements.
  ///
  ///     var numbers = [10, 20, 30, 40, 50]
  ///     print("Count: \(numbers.count), capacity: \(numbers.capacity)")
  ///     // Prints "Count: 5, capacity: 5"
  ///
  ///     numbers.append(contentsOf: stride(from: 60, through: 100, by: 10))
  ///     print("Count: \(numbers.count), capacity: \(numbers.capacity)")
  ///     // Prints "Count: 10, capacity: 12"
  public var capacity: Int {
    return _getCapacity()
  }

  /// An object that guarantees the lifetime of this array's elements.
  public // @testable
  var _owner: AnyObject? {
    return _buffer.owner
  }

  /// If the elements are stored contiguously, a pointer to the first
  /// element. Otherwise, `nil`.
  public var _baseAddressIfContiguous: UnsafeMutablePointer<Element>? {
    return _buffer.firstElementAddressIfContiguous
  }

%if Self != 'Array': # // Array does not necessarily have contiguous storage
  internal var _baseAddress: UnsafeMutablePointer<Element> {
    return _buffer.firstElementAddress
  }
%end
  //===--- basic mutations ------------------------------------------------===//


  /// Reserves enough space to store the specified number of elements.
  ///
  /// If you are adding a known number of elements to an array, use this method
  /// to avoid multiple reallocations. This method ensures that the array has
  /// unique, mutable, contiguous storage, with space allocated for at least
  /// the requested number of elements.
  ///
  /// For performance reasons, the newly allocated storage may be larger than
  /// the requested capacity. Use the array's `capacity` property to determine
  /// the size of the new storage.
  ///
  /// - Parameter minimumCapacity: The requested number of elements to store.
  ///
  /// - Complexity: O(*n*), where *n* is the count of the array.
  @_semantics("array.mutate_unknown")
  public mutating func reserveCapacity(_ minimumCapacity: Int) {
    if _buffer.requestUniqueMutableBackingBuffer(
      minimumCapacity: minimumCapacity) == nil {

      let newBuffer = _ContiguousArrayBuffer<Element>(
        uninitializedCount: count, minimumCapacity: minimumCapacity)

      _buffer._copyContents(
        subRange: Range(_buffer.indices),
        initializing: newBuffer.firstElementAddress)
      _buffer = _Buffer(newBuffer, shiftedToStartIndex: _buffer.startIndex)
    }
    _sanityCheck(capacity >= minimumCapacity)
  }

  /// Copy the contents of the current buffer to a new unique mutable buffer.
  /// The count of the new buffer is set to `oldCount`, the capacity of the
  /// new buffer is big enough to hold 'oldCount' + 1 elements.
  @inline(never)
  internal mutating func _copyToNewBuffer(oldCount: Int) {
    let newCount = oldCount + 1
    var newBuffer = _forceCreateUniqueMutableBuffer(
      &_buffer, countForNewBuffer: oldCount, minNewCapacity: newCount)
    _arrayOutOfPlaceUpdate(
      &_buffer, &newBuffer, oldCount, 0, _IgnorePointer())
  }

  @_semantics("array.make_mutable")
  internal mutating func _makeUniqueAndReserveCapacityIfNotUnique() {
    if _slowPath(!_buffer.isMutableAndUniquelyReferenced()) {
      _copyToNewBuffer(oldCount: _buffer.count)
    }
  }

  @_semantics("array.mutate_unknown")
  internal mutating func _reserveCapacityAssumingUniqueBuffer(oldCount: Int) {
    _sanityCheck(_buffer.isMutableAndUniquelyReferenced())

    if _slowPath(oldCount + 1 > _buffer.capacity) {
      _copyToNewBuffer(oldCount: oldCount)
    }
  }

  @_semantics("array.mutate_unknown")
  internal mutating func _appendElementAssumeUniqueAndCapacity(
    _ oldCount: Int,
    newElement: Element
  ) {
    _sanityCheck(_buffer.isMutableAndUniquelyReferenced())
    _sanityCheck(_buffer.capacity >= _buffer.count + 1)

    _buffer.count = oldCount + 1
    (_buffer.firstElementAddress + oldCount).initialize(with: newElement)
  }

  /// Adds a new element at the end of the array.
  ///
  /// - Parameter newElement: The element to append to the array.
  ///
  /// - Complexity: Appending an element to the array averages to O(1) over
  ///   many additions. When the array needs to reallocate storage before
  ///   appending or its storage is shared with another copy, appending an
  ///   element is O(*n*), where *n* is the length of the array. If the array
  ///   uses a bridged `NSArray` instance as its storage, the efficiency is
  ///   unspecified.
  public mutating func append(_ newElement: Element) {
    _makeUniqueAndReserveCapacityIfNotUnique()
    let oldCount = _getCount()
    _reserveCapacityAssumingUniqueBuffer(oldCount: oldCount)
    _appendElementAssumeUniqueAndCapacity(oldCount, newElement: newElement)
  }

  /// Adds the elements of a sequence to the end of the array.
  ///
  /// Use this method to append the elements of a sequence to the end of a
  /// collection. This example appends the elements of a `Range<Int>` instance
  /// to an array of integers.
  ///
  ///     var numbers = [1, 2, 3, 4, 5]
  ///     numbers.append(contentsOf: 10...15)
  ///     print(numbers)
  ///     // Prints "[1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15]"
  ///
  /// - Parameter newElements: The elements to append to the array.
  ///
  /// - Complexity: O(*n*), where *n* is the length of the resulting array.
  public mutating func append<S : Sequence>(contentsOf newElements: S)
    where S.Iterator.Element == Element {
    let oldCount = self.count
    let capacity = self.capacity
    let newCount = oldCount + newElements.underestimatedCount

    if newCount > capacity {
      self.reserveCapacity(
        Swift.max(newCount, _growArrayCapacity(capacity)))
      }
    _arrayAppendSequence(&self._buffer, newElements)
  }

  // An overload of `append(contentsOf:)` that uses the += that is optimized for
  // collections.
  // FIXME(ABI): remove this entrypoint.  The overload for `Sequence` should be
  // made optimal for this case, too.
  /// Adds the elements of a collection to the end of the array.
  ///
  /// Use this method to append the elements of a collection to the end of this
  /// collection. This example appends the elements of a `Range<Int>` instance
  /// to an array of integers.
  ///
  ///     var numbers = [1, 2, 3, 4, 5]
  ///     numbers.append(contentsOf: 10...15)
  ///     print(numbers)
  ///     // Prints "[1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15]"
  ///
  /// - Parameter newElements: The elements to append to the array.
  ///
  /// - Complexity: O(*n*), where *n* is the length of the resulting array.
  public mutating func append<C : Collection>(contentsOf newElements: C)
    where C.Iterator.Element == Element {

    let newElementsCount = numericCast(newElements.count) as Int

    let oldCount = self.count
    let capacity = self.capacity
    let newCount = oldCount + newElementsCount

    // Ensure uniqueness, mutability, and sufficient storage.  Note that
    // for consistency, we need unique self even if newElements is empty.
    self.reserveCapacity(
      newCount > capacity ?
      Swift.max(newCount, _growArrayCapacity(capacity))
      : newCount)

    (self._buffer.firstElementAddress + oldCount).initializeFrom(newElements)
    self._buffer.count = newCount
  }

  /// Removes and returns the last element of the array.
  ///
  /// The array must not be empty.
  ///
  /// - Returns: The element that was removed.
  @discardableResult
  public mutating func removeLast() -> Element {
    _precondition(count > 0, "can't removeLast from an empty ${Self}")
    let i = count
    // We don't check for overflow in `i - 1` because `i` is known to be
    // positive.
    let result = self[i &- 1]
    self.replaceSubrange((i &- 1)..<i, with: EmptyCollection())
    return result
  }

  /// Inserts a new element at the specified position.
  ///
  /// The new element is inserted before the element currently at the specified
  /// index. If you pass the array's `endIndex` property as the `index`
  /// parameter, the new element is appended to the array.
  ///
  ///     var numbers = [1, 2, 3, 4, 5]
  ///     numbers.insert(100, at: 3)
  ///     numbers.insert(200, at: numbers.endIndex)
  ///
  ///     print(numbers)
  ///     // Prints "[1, 2, 3, 100, 4, 5, 200]"
  ///
  /// - Parameter newElement: The new element to insert into the array.
  /// - Parameter i: The position at which to insert the new element.
  ///   `index` must be a valid index of the array or equal to its `endIndex`
  ///   property.
  ///
  /// - Complexity: O(*n*), where *n* is the length of the array.
  public mutating func insert(_ newElement: Element, at i: Int) {
    _checkIndex(i)
    self.replaceSubrange(i..<i, with: CollectionOfOne(newElement))
  }

  /// Removes and returns the element at the specified position.
  ///
  /// All the elements following the specified position are moved up to
  /// close the gap.
  ///
  ///     var measurements: [Double] = [1.1, 1.5, 2.9, 1.2, 1.5, 1.3, 1.2]
  ///     let removed = measurements.remove(at: 2)
  ///     print(measurements)
  ///     // Prints "[1.1, 1.5, 1.2, 1.5, 1.3, 1.2]"
  ///
  /// - Parameter index: The position of the element to remove. `index` must
  ///   be a valid index of the array.
  /// - Returns: The element at the specified index.
  ///
  /// - Complexity: O(*n*), where *n* is the length of the array.
  @discardableResult
  public mutating func remove(at index: Int) -> Element {
    let result = self[index]
    self.replaceSubrange(index..<(index + 1), with: EmptyCollection())
    return result
  }

  /// Removes all elements from the array.
  ///
  /// - Parameter keepCapacity: Pass `true` to keep the existing capacity of
  ///   the array after removing its elements. The default value is
  ///   `false`.
  ///
  /// - Complexity: O(*n*), where *n* is the length of the array.
  public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
    if !keepCapacity {
      _buffer = _Buffer()
    }
    else {
      self.replaceSubrange(Range(self.indices), with: EmptyCollection())
    }
  }

  //===--- algorithms -----------------------------------------------------===//

  public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
    _ body: @noescape (UnsafeMutablePointer<Element>, Int) throws -> R
  ) rethrows -> R? {
    return try withUnsafeMutableBufferPointer {
      (bufferPointer) -> R in
      let r = try body(bufferPointer.baseAddress!, bufferPointer.count)
      return r
    }
  }

  public func _copyToNativeArrayBuffer() -> _ContiguousArrayBuffer<Element> {
    return _extractOrCopyToNativeArrayBuffer(self._buffer)
  }
}

extension ${Self} : CustomReflectable {
  /// A mirror that reflects the array.
  public var customMirror: Mirror {
    return Mirror(
      self,
      unlabeledChildren: self,
      displayStyle: .collection)
  }
}

extension ${Self} : CustomStringConvertible, CustomDebugStringConvertible {
  internal func _makeDescription(isDebug: Bool) -> String {
%   if Self != 'Array':
    var result = isDebug ? "${Self}([" : "["
%   else:
    // Always show sugared representation for Arrays.
    var result = "["
%   end
    var first = true
    for item in self {
      if first {
        first = false
      } else {
        result += ", "
      }
      debugPrint(item, terminator: "", to: &result)
    }
%   if Self != 'Array':
    result += isDebug ? "])" : "]"
%   else:
    // Always show sugared representation for Arrays.
    result += "]"
%   end
    return result
  }

  /// A textual representation of the array and its elements.
  public var description: String {
    return _makeDescription(isDebug: false)
  }

  /// A textual representation of the array and its elements, suitable for
  /// debugging.
  public var debugDescription: String {
    return _makeDescription(isDebug: true)
  }
}

extension ${Self} {
  @_versioned
  @_transparent
  internal func _cPointerArgs() -> (AnyObject?, UnsafePointer<Void>?) {
    let p = _baseAddressIfContiguous
    if _fastPath(p != nil || isEmpty) {
      return (_owner, UnsafePointer(p))
    }
    let n = _extractOrCopyToNativeArrayBuffer(self._buffer)
    return (n.owner, UnsafePointer(n.firstElementAddress))
  }

}

extension ${Self} {
  /// Calls a closure with a pointer to the array's contiguous storage.
  /// ${contiguousCaveat}
  ///
  /// Often, the optimizer can eliminate bounds checks within an array
  /// algorithm, but when that fails, invoking the same algorithm on the
  /// buffer pointer passed into your closure lets you trade safety for speed.
  ///
  /// The following example shows how you can iterate over the contents of the
  /// buffer pointer:
  ///
  ///     let numbers = [1, 2, 3, 4, 5]
  ///     let sum = numbers.withUnsafeBufferPointer { buffer -> Int in
  ///         var result = 0
  ///         for i in stride(from: buffer.startIndex, to: buffer.endIndex, by: 2) {
  ///             result += buffer[i]
  ///         }
  ///         return result
  ///     }
  ///     // 'sum' == 9
  ///
  /// - Parameter body: A closure with an `UnsafeBufferPointer` parameter that
  ///   points to the contiguous storage for the array. If `body` has a return
  ///   value, it is used as the return value for the
  ///   `withUnsafeBufferPointer(_:)` method. The pointer argument is valid
  ///   only for the duration of the closure's execution.
  /// - Returns: The return value of the `body` closure parameter, if any.
  ///
  /// - SeeAlso: `withUnsafeMutableBufferPointer`, `UnsafeBufferPointer`
  public func withUnsafeBufferPointer<R>(
    _ body: @noescape (UnsafeBufferPointer<Element>) throws -> R
  ) rethrows -> R {
    return try _buffer.withUnsafeBufferPointer(body)
  }

  /// Calls the given closure with a pointer to the array's mutable contiguous
  /// storage.${contiguousCaveat}
  ///
  /// Often, the optimizer can eliminate bounds checks within an array
  /// algorithm, but when that fails, invoking the same algorithm on the
  /// buffer pointer passed into your closure lets you trade safety for speed.
  ///
  /// The following example shows modifying the contents of the
  /// `UnsafeMutableBufferPointer` argument to `body` alters the contents of
  /// the array:
  ///
  ///     var numbers = [1, 2, 3, 4, 5]
  ///     numbers.withUnsafeMutableBufferPointer { buffer in
  ///         for i in stride(from: buffer.startIndex, to: buffer.endIndex - 1, by: 2) {
  ///             swap(&buffer[i], &buffer[i + 1])
  ///         }
  ///     }
  ///     print(numbers)
  ///     // Prints "[2, 1, 4, 3, 5]"
  ///
  /// - Warning: Do not rely on anything about `self` (the array that is the
  ///   target of this method) during the execution of the `body` closure: It
  ///   may not appear to have its correct value.  Instead, use only the
  ///   `UnsafeMutableBufferPointer` argument to `body`.
  ///
  /// - Parameter body: A closure with an `UnsafeMutableBufferPointer`
  ///   parameter that points to the contiguous storage for the array. If
  ///   `body` has a return value, it is used as the return value for the
  ///   `withUnsafeMutableBufferPointer(_:)` method. The pointer argument is
  ///   valid only for the duration of the closure's execution.
  /// - Returns: The return value of the `body` closure parameter, if any.
  ///
  /// - SeeAlso: `withUnsafeBufferPointer`, `UnsafeMutableBufferPointer`
  @_semantics("array.withUnsafeMutableBufferPointer")
  @inline(__always) // Performance: This method should get inlined into the
  // caller such that we can combine the partial apply with the apply in this
  // function saving on allocating a closure context. This becomes unnecessary
  // once we allocate noescape closures on the stack.
  public mutating func withUnsafeMutableBufferPointer<R>(
    _ body: @noescape (inout UnsafeMutableBufferPointer<Element>) throws -> R
  ) rethrows -> R {
    let count = self.count
    // Ensure unique storage
    _outlinedMakeUniqueBuffer(&_buffer, bufferCount: count)

    // Ensure that body can't invalidate the storage or its bounds by
    // moving self into a temporary working array.
    // NOTE: The stack promotion optimization that keys of the
    // "array.withUnsafeMutableBufferPointer" semantics annotation relies on the
    // array buffer not being able to escape in the closure. It can do this
    // because we swap the array buffer in self with an empty buffer here. Any
    // escape via the address of self in the closure will therefore escape the
    // empty array.

    var work = ${Self}()
    swap(&work, &self)

    // Create an UnsafeBufferPointer over work that we can pass to body
    let pointer = work._buffer.firstElementAddress
    var inoutBufferPointer = UnsafeMutableBufferPointer(
      start: pointer, count: count)

    // Put the working array back before returning.
    defer {
      _precondition(
        inoutBufferPointer.baseAddress == pointer &&
        inoutBufferPointer.count == count,
        "${Self} withUnsafeMutableBufferPointer: replacing the buffer is not allowed")

      swap(&work, &self)
    }

    // Invoke the body.
    return try body(&inoutBufferPointer)
  }
}
%end

internal struct _InitializeMemoryFromCollection<
  C: Collection
> : _PointerFunction {
  func call(_ rawMemory: UnsafeMutablePointer<C.Iterator.Element>, count: Int) {
    var p = rawMemory
    var q = newValues.startIndex
    for _ in 0..<count {
      p.initialize(with: newValues[q])
      newValues.formIndex(after: &q)
      p += 1
    }
    _expectEnd(q, newValues)
  }

  init(_ newValues: C) {
    self.newValues = newValues
  }

  var newValues: C
}

// FIXME(ABI): add argument labels.
@inline(never)
internal func _arrayOutOfPlaceReplace<B, C>(
  _ source: inout B,
  _ bounds: Range<Int>,
  _ newValues: C,
  _ insertCount: Int
) where
  B : _ArrayBufferProtocol,
  C : Collection,
  C.Iterator.Element == B.Element,
  B.Index == Int {

  let growth = insertCount - bounds.count
  let newCount = source.count + growth
  var newBuffer = _forceCreateUniqueMutableBuffer(
    &source, newCount: newCount, requiredCapacity: newCount)

  _arrayOutOfPlaceUpdate(
    &source, &newBuffer,
    bounds.lowerBound - source.startIndex, insertCount,
    _InitializeMemoryFromCollection(newValues)
  )
}

/// A _debugPrecondition check that `i` has exactly reached the end of
/// `s`.  This test is never used to ensure memory safety; that is
/// always guaranteed by measuring `s` once and re-using that value.
// FIXME(ABI): add argument labels.
internal func _expectEnd<C : Collection>(_ i: C.Index, _ s: C) {
  _debugPrecondition(
    i == s.endIndex,
    "invalid Collection: count differed in successive traversals")
}

internal func _growArrayCapacity(_ capacity: Int) -> Int {
  return capacity * 2
}

% for (Self, a_Self) in arrayTypes:
extension ${Self} {
  /// Replaces a range of elements with the elements in the specified
  /// collection.
  ///
  /// This method has the effect of removing the specified range of elements
  /// from the array and inserting the new elements at the same location. The
  /// number of new elements need not match the number of elements being
  /// removed.
  ///
  /// In this example, three elements in the middle of an array of integers are
  /// replaced by the five elements of a `Repeated<Int>` instance.
  ///
  ///      var nums = [10, 20, 30, 40, 50]
  ///      nums.replaceSubrange(1...3, with: repeatElement(1, count: 5))
  ///      print(nums)
  ///      // Prints "[10, 1, 1, 1, 1, 1, 50]"
  ///
  /// If you pass a zero-length range as the `subrange` parameter, this method
  /// inserts the elements of `newElements` at `subrange.startIndex`. Calling
  /// the `insert(contentsOf:at:)` method instead is preferred.
  ///
  /// Likewise, if you pass a zero-length collection as the `newElements`
  /// parameter, this method removes the elements in the given subrange
  /// without replacement. Calling the `removeSubrange(_:)` method instead is
  /// preferred.
  ///
  /// - Parameters:
  ///   - subrange: The subrange of the array to replace. The start and end of
  ///     a subrange must be valid indices of the array.
  ///   - newElements: The new elements to add to the array.
  ///
  /// - Complexity: O(`subrange.count`) if you are replacing a suffix of the
  ///   array with an empty collection; otherwise, O(*n*), where *n* is the
  ///   length of the array.
  @_semantics("array.mutate_unknown")
  public mutating func replaceSubrange<C>(
    _ subrange: Range<Int>,
    with newElements: C
  ) where C : Collection, C.Iterator.Element == _Buffer.Element {
    _precondition(subrange.lowerBound >= self._buffer.startIndex,
      "${Self} replace: subrange start is negative")

    _precondition(subrange.upperBound <= self._buffer.endIndex,
      "${Self} replace: subrange extends past the end")

    let oldCount = self._buffer.count
    let eraseCount = subrange.count
    let insertCount = numericCast(newElements.count) as Int
    let growth = insertCount - eraseCount

    if self._buffer.requestUniqueMutableBackingBuffer(
      minimumCapacity: oldCount + growth) != nil {

      self._buffer.replace(
        subRange: subrange, with: insertCount, elementsOf: newElements)
    } else {
      _arrayOutOfPlaceReplace(&self._buffer, subrange, newElements, insertCount)
    }
  }
}

// FIXME(ABI): remove this entrypoint.  The functionality should be provided by
// a `+=` operator on `RangeReplaceableCollection`.
/// Appends the elements of a sequence to ${a_Self}.
///
/// Use this operator to append the elements of a sequence to the end of
/// ${a_Self} with same `Element` type. This example appends
/// the elements of a `Range<Int>` instance to an array of integers.
///
///     var numbers = [1, 2, 3, 4, 5]
///     numbers += 10...15
///     print(numbers)
///     // Prints "[1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15]"
///
/// - Parameters:
///   - lhs: The array to append to.
///   - rhs: A collection or finite sequence.
///
/// - Complexity: O(*n*), where *n* is the length of the resulting array.
public func += <
  S : Sequence
>(lhs: inout ${Self}<S.Iterator.Element>, rhs: S) {
  lhs.append(contentsOf: rhs)
}

// FIXME(ABI): remove this entrypoint.  The functionality should be provided by
// a `+=` operator on `RangeReplaceableCollection`.
/// Appends the elements of a collection to ${a_Self}.
///
/// Use this operator to append the elements of a collection to the end of
/// ${a_Self} with same `Element` type. This example appends
/// the elements of a `Range<Int>` instance to an array of integers.
///
///     var numbers = [1, 2, 3, 4, 5]
///     numbers += 10...15
///     print(numbers)
///     // Prints "[1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15]"
///
/// - Parameters:
///   - lhs: The array to append to.
///   - rhs: A collection.
///
/// - Complexity: O(*n*), where *n* is the length of the resulting array.
public func += <
  C : Collection
>(lhs: inout ${Self}<C.Iterator.Element>, rhs: C) {
  lhs.append(contentsOf: rhs)
}
% end

//===--- generic helpers --------------------------------------------------===//

/// Create a unique mutable buffer that has enough capacity to hold 'newCount'
/// elements and at least 'requiredCapacity' elements. Set the count of the new
/// buffer to 'newCount'. The content of the buffer is uninitialized.
/// The formula used to compute the new buffers capacity is:
///   max(requiredCapacity, source.capacity)  if newCount <= source.capacity
///   max(requiredCapacity, _growArrayCapacity(source.capacity)) otherwise
@inline(never)
internal func _forceCreateUniqueMutableBuffer<_Buffer : _ArrayBufferProtocol>(
  _ source: inout _Buffer, newCount: Int, requiredCapacity: Int
) -> _ContiguousArrayBuffer<_Buffer.Element> {
  return _forceCreateUniqueMutableBufferImpl(
    &source, countForBuffer: newCount, minNewCapacity: newCount,
    requiredCapacity: requiredCapacity)
}

/// Create a unique mutable buffer that has enough capacity to hold
/// 'minNewCapacity' elements and set the count of the new buffer to
/// 'countForNewBuffer'. The content of the buffer uninitialized.
/// The formula used to compute the new buffers capacity is:
///   max(minNewCapacity, source.capacity) if minNewCapacity <= source.capacity
///   max(minNewCapacity, _growArrayCapacity(source.capacity)) otherwise
@inline(never)
internal
func _forceCreateUniqueMutableBuffer<_Buffer : _ArrayBufferProtocol>(
  _ source: inout _Buffer, countForNewBuffer: Int, minNewCapacity: Int
) -> _ContiguousArrayBuffer<_Buffer.Element> {
  return _forceCreateUniqueMutableBufferImpl(
    &source, countForBuffer: countForNewBuffer, minNewCapacity: minNewCapacity,
    requiredCapacity: minNewCapacity)
}

/// Create a unique mutable buffer that has enough capacity to hold
/// 'minNewCapacity' elements and at least 'requiredCapacity' elements and set
/// the count of the new buffer to 'countForBuffer'. The content of the buffer
/// uninitialized.
/// The formula used to compute the new capacity is:
///  max(requiredCapacity, source.capacity) if minNewCapacity <= source.capacity
///  max(requiredCapacity, _growArrayCapacity(source.capacity))  otherwise
internal func _forceCreateUniqueMutableBufferImpl<_Buffer : _ArrayBufferProtocol>(
  _ source: inout _Buffer, countForBuffer: Int, minNewCapacity: Int,
  requiredCapacity: Int
) -> _ContiguousArrayBuffer<_Buffer.Element> {
  _sanityCheck(countForBuffer >= 0)
  _sanityCheck(requiredCapacity >= countForBuffer)
  _sanityCheck(minNewCapacity >= countForBuffer)

  let minimumCapacity = max(
    requiredCapacity, minNewCapacity > source.capacity
      ? _growArrayCapacity(source.capacity) : source.capacity)

  return _ContiguousArrayBuffer(
    uninitializedCount: countForBuffer, minimumCapacity: minimumCapacity)
}

internal protocol _PointerFunction {
  associatedtype Element
  func call(_: UnsafeMutablePointer<Element>, count: Int)
}

/// Initialize the elements of dest by copying the first headCount
/// items from source, calling initializeNewElements on the next
/// uninitialized element, and finally by copying the last N items
/// from source into the N remaining uninitialized elements of dest.
///
/// As an optimization, may move elements out of source rather than
/// copying when it isUniquelyReferenced.
@inline(never)
internal func _arrayOutOfPlaceUpdate<_Buffer, Initializer>(
  _ source: inout _Buffer,
  _ dest: inout _ContiguousArrayBuffer<_Buffer.Element>,
  _ headCount: Int, // Count of initial source elements to copy/move
  _ newCount: Int,  // Number of new elements to insert
  _ initializeNewElements: Initializer
) where
  _Buffer : _ArrayBufferProtocol,
  Initializer : _PointerFunction,
  Initializer.Element == _Buffer.Element,
  _Buffer.Index == Int {

  _sanityCheck(headCount >= 0)
  _sanityCheck(newCount >= 0)

  // Count of trailing source elements to copy/move
  let tailCount = dest.count - headCount - newCount
  _sanityCheck(headCount + tailCount <= source.count)

  let sourceCount = source.count
  let oldCount = sourceCount - headCount - tailCount
  let destStart = dest.firstElementAddress
  let newStart = destStart + headCount
  let newEnd = newStart + newCount

  // Check to see if we have storage we can move from
  if let backing = source.requestUniqueMutableBackingBuffer(
    minimumCapacity: sourceCount) {

    let sourceStart = source.firstElementAddress
    let oldStart = sourceStart + headCount

    // Destroy any items that may be lurking in a _SliceBuffer before
    // its real first element
    let backingStart = backing.firstElementAddress
    let sourceOffset = sourceStart - backingStart
    backingStart.deinitialize(count: sourceOffset)

    // Move the head items
    destStart.moveInitializeFrom(sourceStart, count: headCount)

    // Destroy unused source items
    oldStart.deinitialize(count: oldCount)

    initializeNewElements.call(newStart, count: newCount)

    // Move the tail items
    newEnd.moveInitializeFrom(oldStart + oldCount, count: tailCount)

    // Destroy any items that may be lurking in a _SliceBuffer after
    // its real last element
    let backingEnd = backingStart + backing.count
    let sourceEnd = sourceStart + sourceCount
    sourceEnd.deinitialize(count: backingEnd - sourceEnd)
    backing.count = 0
  }
  else {
    let headStart = source.startIndex
    let headEnd = headStart + headCount
    let newStart = source._copyContents(
      subRange: headStart..<headEnd,
      initializing: destStart)
    initializeNewElements.call(newStart, count: newCount)
    let tailStart = headEnd + oldCount
    let tailEnd = source.endIndex
    source._copyContents(subRange: tailStart..<tailEnd, initializing: newEnd)
  }
  source = _Buffer(dest, shiftedToStartIndex: source.startIndex)
}

internal struct _InitializePointer<T> : _PointerFunction {
  internal func call(_ rawMemory: UnsafeMutablePointer<T>, count: Int) {
    _sanityCheck(count == 1)
    // FIXME: it would be better if we could find a way to move, here
    rawMemory.initialize(with: newValue)
  }

  @_transparent
  internal init(_ newValue: T) {
    self.newValue = newValue
  }

  internal var newValue: T
}

internal struct _IgnorePointer<T> : _PointerFunction {
  internal func call(_: UnsafeMutablePointer<T>, count: Int) {
    _sanityCheck(count == 0)
  }
}

@_versioned
@inline(never)
internal func _outlinedMakeUniqueBuffer<_Buffer>(
  _ buffer: inout _Buffer, bufferCount: Int
) where
  _Buffer : _ArrayBufferProtocol,
  _Buffer.Index == Int {

  if _fastPath(
      buffer.requestUniqueMutableBackingBuffer(minimumCapacity: bufferCount) != nil) {
    return
  }

  var newBuffer = _forceCreateUniqueMutableBuffer(
    &buffer, newCount: bufferCount, requiredCapacity: bufferCount)
  _arrayOutOfPlaceUpdate(&buffer, &newBuffer, bufferCount, 0, _IgnorePointer())
}

internal func _arrayReserve<_Buffer>(
  _ buffer: inout _Buffer, _ minimumCapacity: Int
) where
  _Buffer : _ArrayBufferProtocol,
  _Buffer.Index == Int {

  let count = buffer.count
  let requiredCapacity = max(count, minimumCapacity)

  if _fastPath(
      buffer.requestUniqueMutableBackingBuffer(
        minimumCapacity: requiredCapacity) != nil
  ) {
    return
  }

  var newBuffer = _forceCreateUniqueMutableBuffer(
    &buffer, newCount: count, requiredCapacity: requiredCapacity)
  _arrayOutOfPlaceUpdate(&buffer, &newBuffer, count, 0, _IgnorePointer())
}

public // SPI(Foundation)
func _extractOrCopyToNativeArrayBuffer<Buffer>(
  _ source: Buffer
) -> _ContiguousArrayBuffer<Buffer.Iterator.Element>
  where
  Buffer : _ArrayBufferProtocol,
  Buffer.Iterator.Element == Buffer.Element {

  if let n = source.requestNativeBuffer() {
    return n
  }
  return _copyCollectionToNativeArrayBuffer(source)
}

/// Append items from `newItems` to `buffer`.
internal func _arrayAppendSequence<Buffer, S>(
  _ buffer: inout Buffer, _ newItems: S
) where
  Buffer : _ArrayBufferProtocol,
  S : Sequence,
  S.Iterator.Element == Buffer.Element,
  Buffer.Index == Int {

  var stream = newItems.makeIterator()
  var nextItem = stream.next()

  if nextItem == nil {
    return
  }

  // This will force uniqueness
  var count = buffer.count
  _arrayReserve(&buffer, count + 1)
  while true {
    let capacity = buffer.capacity
    let base = buffer.firstElementAddress

    while (nextItem != nil) && count < capacity {
      (base + count).initialize(with: nextItem!)
      count += 1
      nextItem = stream.next()
    }
    buffer.count = count
    if nextItem == nil {
      return
    }
    _arrayReserve(&buffer, _growArrayCapacity(capacity))
  }
}

% for (Self, a_Self) in arrayTypes:
// NOTE: The '==' and '!=' below only handles array types
// that are the same, e.g. Array<Int> and Array<Int>, not
// ArraySlice<Int> and Array<Int>.

/// Returns `true` if these arrays contain the same elements.
public func == <Element : Equatable>(
  lhs: ${Self}<Element>, rhs: ${Self}<Element>
) -> Bool {
  let lhsCount = lhs.count
  if lhsCount != rhs.count {
    return false
  }

  // Test referential equality.
  if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity {
    return true
  }

%if Self == 'ArraySlice':

  var streamLHS = lhs.makeIterator()
  var streamRHS = rhs.makeIterator()

  var nextLHS = streamLHS.next()
  while nextLHS != nil {
    let nextRHS = streamRHS.next()
    if nextLHS != nextRHS {
      return false
    }
    nextLHS = streamLHS.next()
  }

%else:

  _sanityCheck(lhs.startIndex == 0 && rhs.startIndex == 0)
  _sanityCheck(lhs.endIndex == lhsCount && rhs.endIndex == lhsCount)

  // We know that lhs.count == rhs.count, compare element wise.
  for idx in 0..<lhsCount {
    if lhs[idx] != rhs[idx] {
      return false
    }
  }
%end

  return true
}

/// Returns `true` if the arrays do not contain the same elements.
public func != <Element : Equatable>(
  lhs: ${Self}<Element>, rhs: ${Self}<Element>
) -> Bool {
  return !(lhs == rhs)
}
%end

#if _runtime(_ObjC)
/// Returns an `Array<Base>` containing the same elements as `a` in
/// O(1).
///
/// - Precondition: `Base` is a base class or base `@objc` protocol (such
///   as `AnyObject`) of `Derived`.
public func _arrayUpCast<Derived, Base>(_ a: Array<Derived>) -> Array<Base> {
  // FIXME: Dynamic casting is currently not possible without the objc runtime:
  // rdar://problem/18801510
  return Array(_buffer: a._buffer.cast(toBufferOf: Base.self))
}
#endif

#if _runtime(_ObjC)
extension Array {
  /// Tries to downcast the source `NSArray` as our native buffer type.
  /// If it succeeds, creates a new `Array` around it and returns that.
  /// Returns `nil` otherwise.
  // Note: this function exists here so that Foundation doesn't have
  // to know Array's implementation details.
  public static func _bridgeFromObjectiveCAdoptingNativeStorageOf(
    _ source: AnyObject
  ) -> Array? {
    if let deferred = source as? _SwiftDeferredNSArray {
      if let nativeStorage =
        deferred._nativeStorage as? _ContiguousArrayStorage<Element> {
        return Array(_ContiguousArrayBuffer(nativeStorage))
      }
    }
    return nil
  }

  /// Private initializer used for bridging.
  ///
  /// Only use this initializer when both conditions are true:
  ///
  /// * it is statically known that the given `NSArray` is immutable;
  /// * `Element` is bridged verbatim to Objective-C (i.e.,
  ///   is a reference type).
  public init(_immutableCocoaArray: _NSArrayCore) {
    self = Array(_buffer: _ArrayBuffer(nsArray: _immutableCocoaArray))
  }
}
#endif

extension Array {
  /// Removes and returns the last element of the array.
  ///
  /// - Returns: The last element of the array if the array is not empty;
  ///   otherwise, `nil`.
  ///
  /// - Complexity: O(*n*) if the array is bridged, where *n* is the length
  ///   of the array; otherwise, O(1).
  /// - SeeAlso: `removeLast()`
  public mutating func popLast() -> Element? {
    guard !isEmpty else { return nil }
    return removeLast()
  }
}

extension ContiguousArray {
  /// Removes and returns the last element of the array.
  ///
  /// - Returns: The last element of the array if the array is not empty;
  ///   otherwise, `nil`.
  ///
  /// - Complexity: O(1)
  /// - SeeAlso: `removeLast()`
  public mutating func popLast() -> Element? {
    guard !isEmpty else { return nil }
    return removeLast()
  }
}

%for (Self, a_Self) in arrayTypes:
extension ${Self} {
  @available(*, unavailable, message: "Please use init(repeating:count:) instead")
  init(count: Int, repeatedValue: Element) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "remove(at:)")
  public mutating func removeAtIndex(_ index: Int) -> Element {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "replaceSubrange")
  public mutating func replaceRange<C>(
    _ subRange: Range<Int>,
    with newElements: C
  ) where C : Collection, C.Iterator.Element == _Buffer.Element {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "append(contentsOf:)")
  public mutating func appendContentsOf<S : Sequence>(_ newElements: S)
    where S.Iterator.Element == Element {
    Builtin.unreachable()
  }
}
%end

// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:
